package server;

import java.io.File;
import database.Database;
import security.SealedObj;
import security.Signature;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import communication.Connection;
import communication.ConnectionException;
import database.DatabaseOperationsCapsules;
import database.DatabaseOperationsIdentifiers;
import java.util.concurrent.atomic.AtomicBoolean;
import communication.ServerSecureConnectionManager;
import constans.ErrorConstants;
import constans.WarningConstantes;

public class ReplicationManager extends Process {

    private Replicator  replicator;
    private int maxReplication;


    public ReplicationManager(Database database, Signature signature, SealedObj sealdObj, int portServer, int maxUsers,
                              File folderCapsule, Logger logger, int maxReplication)
            throws SQLException {
        this.authenticator   =  new Authenticator(new DatabaseOperationsIdentifiers(database.getConnection()), sealdObj, signature);
        this.replicator         =  new Replicator(new DatabaseOperationsCapsules(database.getConnection()));
        this.verifier             =  new Verifier(new DatabaseOperationsCapsules(database.getConnection()));
        this.updater            = new Updater(new DatabaseOperationsIdentifiers(database.getConnection()));
        this.folderCapsule  = folderCapsule;
        this.portServer        = portServer;
        this.maxUsers         = maxUsers;
        this.logger               = logger;
        this.maxReplication  = maxReplication;
        this.isStable             = new AtomicBoolean(true);
    }


    public void run() {
        
        Connection connection = null;

        try {
            serverSecureConnectionManager = new ServerSecureConnectionManager(portServer);
        } catch (ConnectionException e) {
            logger.log(Level.SEVERE, "Error code ("+ErrorConstants.ERROR_CONNECTION+" ): "+e.getMessage());
            System.exit(ErrorConstants.ERROR_CONNECTION);
        }


        while (isStable.get()) {

            try {

                    logger.log(Level.INFO, "Waiting....");
                    connection = serverSecureConnectionManager.acceptConnection();

                    if(authenticator.getNumberIdentifiers() < maxUsers){
                        new ThreadReplication(connection, authenticator, replicator, verifier, updater, folderCapsule, isStable, logger,
                                maxReplication).start();
                    }
                    else{
                           logger.log(Level.WARNING,"Warning code("+WarningConstantes.WARNING_MAX_USERS+"): Too many users");
                           closeConnection(connection);
                    }
           } catch (ConnectionException e) {
                logger.log(Level.WARNING, "Warning code("+WarningConstantes.WARNING_CONNECTION+"): "+e.getMessage());
                closeConnection(connection);
           }       

        }
        //TODO
        System.exit(1);
    }


    public void stopRun() {
        if (serverSecureConnectionManager != null) {
            try {
                serverSecureConnectionManager.close();
            } catch (ConnectionException ex) {}
        }
        
        isStable.set(false);
    }


    private void closeConnection(Connection connection){
          if (connection != null) {
                        try {
                            connection.close();
                        } catch (ConnectionException ex) {}
                        connection = null;
           }
    }

    
}

